import { useEffect, useRef, useState } from 'react';
import { BrowserRouter as Router, Route, Link } from 'react-router-dom';

// import { App2 } from './App2';

type Channel = {
  id: number;
  name: string;
};

// 函数组件
export const App1 = () => {
  // hooks

  // 页面状态 state
  const [count, setCount] = useState<number>(0);
  const [name, setName] = useState('Jack');
  const [obj, setObj] = useState({ name: 'Jack', age: 18 });
  const [arr, setArr] = useState([1, 2, 3]);
  const [arrObj, setArrObj] = useState<{ id: number; name: string }[]>([
    { id: 1, name: 'React' },
  ]);
  // 从网络获取一个对象数组格式的列表
  const [list, setList] = useState<Channel[]>([]);
  // 不使用类型别名指定方式
  const [list2, setList2] = useState<{ id: number; name: string }[]>([]);
  const [list3, setList3] = useState([]);
  // 获取一个也迷啊渲染完毕后的某一个DOM 实例
  const domRef = useRef<HTMLInputElement>(null);
  // const domRef = useRef(null);

  // 不使用 TS 类型推断写法
  // const [arrObj, setArrObj] = useState<{id: number, name: string}[]>([{ id: 1, name: 'React' }]);

  // console.log('====');
  // 引入副作用（模仿声明周期）
  // UI 渲染完毕后，给window添加一个事件监听函数
  useEffect(() => {
    // 每次UI渲染完毕后执行 useEffect
    // 给window添加一个事件监听函数
    console.log('添加');
    const resize = () => console.log('窗口大小变化了');
    window.addEventListener('resize', resize);
    // window.onresize = resize;
    // 清理函数-组件卸载的时候
    return () => {
      console.log('清除');
      window.removeEventListener('resize', resize);
    };
  }, []);

  // 页面事件
  const handleInput = () => {
    // hack
    // if (domRef.current === null) return;
    // 鼠标放上去，可以看到是 never 类型
    // console.log(domRef.current);
    // 开发者非常确定它就是一个 HTMLInputElement
    // const el = domRef.current as HTMLInputElement;
    // console.log(el.value);

    // 操作原生dom，可选链操作符，获取 value
    // console.log(domRef.current?.value);

    // 使用非空断言，获取value
    // console.log(domRef.current!.value);
    // if (domRef.current === null) return;
    // // 类型收缩
    // console.log(domRef.current.value);

    // // 类型收缩举例
    // function fn(x: number | string): void {
    //   if (typeof x === 'number') {
    //     // 鼠标放在 x 上查看类型为：
    //     console.log(x);
    //   } else if (typeof x === 'string') {
    //     // 此时，x 的类型为：
    //     console.log(x.length);
    //   } else {
    //     // 此时，x 的类型为：never
    //     console.log(x);
    //   }
    // }

    // 最后总结，如果对象上的某一个属性可能为空或undefined的情况下，你正确访问这个属性的写法。
    // 1 && 操作符
    // console.log(domRef.current && domRef.current.value);
    // 2 三元表达式
    // console.log(domRef.current ? domRef.current.value : '不存在');
    // 3 条件判断
    // if(!domRef.current) return
    // console.log(domRef.current.value)
    // 4 可选链操作符
    console.log('可选链', domRef.current?.value);
    // 5 非空断言
    // console.log('非空断言', domRef.current!.value);
  };

  const handleCount = () => {
    // 修改页面状态了
    // setCount(count + 1);
    // setName('Rose');
    // setObj({ name: 'xx', age: 123 });
    // setArr([1, 2]);
    // setArrObj([{ id: 1, name: 'xxx' }]);
    // 获取到了频道列表数据
    // setList([{ id: 1, name: 'html' }]);
    // setList2([{ id: 1, name: 'html' }]);
    // 1
    // let fn = () => {
    //   // 手动通过 throw 抛出一个异常（错误）
    //   throw new Error('err...');
    //   // 代码无法到达
    //   console.log('我无法到达');
    // };
    // let n1 = fn(); // n => never
    // // n1 = 123
    // // 2
    // let fn2 = () => {
    //   while (true) {}
    //   console.log('我无法到达');
    // };
    // let n2 = fn2(); // n => never

    // // 3
    // const num = 123;
    // if (num !== 123) {
    //   let n = num; // n => never
    // }
    interface Foo {
      type: 'foo';
    }

    interface Bar {
      type: 'bar';
    }

    interface Baz {
      type: 'Baz';
    }

    type All = Foo | Bar | Baz;

    function handleValue(val: All) {
      switch (val.type) {
        case 'foo':
          // 这里 val 被收窄为 Foo
          console.log(val.type);
          break;
        case 'bar':
          // val 在这里是 Bar
          console.log(val.type);
          break;
        case 'Baz':
          // val 在这里是 Baz
          console.log(val.type);
          break;
        default:
          // val 在这里是 never
          console.log(val);
          const exhaustiveCheck: never = val;
          break;
      }
    }
  };

  return (
    <div>
      <h3>Learn React</h3>
      {/* {count > 5 ? null : <App2 />} */}
      <h4>{count}</h4>
      <button onClick={handleCount}>+1</button>
      <br />
      <input type={'text'} ref={domRef} />
      <button onClick={handleInput}>获取输入</button>
    </div>
  );
};
